package com.atguigu.gulimall.product.service.impl;

import com.atguigu.common.constant.ProductConstant;
import com.atguigu.gulimall.product.dao.AttrAttrgroupRelationDao;
import com.atguigu.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.atguigu.gulimall.product.entity.AttrGroupEntity;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.AttrAttrgroupRelationService;
import com.atguigu.gulimall.product.service.AttrGroupService;
import com.atguigu.gulimall.product.service.CategoryService;
import com.atguigu.gulimall.product.vo.AttrGroupRelationVo;
import com.atguigu.gulimall.product.vo.AttrRespVo;
import com.atguigu.gulimall.product.vo.AttrVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.AttrDao;
import com.atguigu.gulimall.product.entity.AttrEntity;
import com.atguigu.gulimall.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * attr表示属性
 */

@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    @Autowired
    private AttrAttrgroupRelationService attrAttrgroupRelationService;

    @Autowired
    private AttrGroupService attrGroupService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private AttrAttrgroupRelationDao attrAttrgroupRelationDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    @Transactional
    @Override
    public void saveAttr(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();

        // 将属性封装到我们的attrEntity实体类
        BeanUtils.copyProperties(attr, attrEntity);
        // 1.先保存基本信息
        save(attrEntity);

        // 2.然后在保存其他的信息(分组信息)
        // 因为我们是共用的一个表 所以销售属性是没有分组信息的
        // 基本属性才进行分组  attr.getAttrGroupId() != null 分组id也不能为空才能保存
        if (attr.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attr.getAttrGroupId() != null) {
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrGroupId(attr.getAttrGroupId());
            attrAttrgroupRelationEntity.setAttrId(attrEntity.getAttrId());
            attrAttrgroupRelationService.save(attrAttrgroupRelationEntity);
        }

    }

    //    分页查询我们的规格参数列表
    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String attrType) {


        LambdaQueryWrapper<AttrEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        lambdaQueryWrapper.eq(AttrEntity::getAttrType, "base".equalsIgnoreCase(attrType) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());

        if (catelogId != 0) {
            // 表示查询所有
            lambdaQueryWrapper.eq(AttrEntity::getCatelogId, catelogId);
        }

        String key = (String) params.get("key");

        if (!StringUtils.isEmpty(key)) {
            // 把这个看成整体然后就实现了and 和 or
            lambdaQueryWrapper.and((obj) -> {
                obj.eq(AttrEntity::getAttrId, key).or().like(AttrEntity::getAttrName, key);
            });

        }

        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                lambdaQueryWrapper
        );

        List<AttrEntity> records = page.getRecords();

        // 最终返回给页面的数据
        List<AttrRespVo> respVos = records.stream().map((attrEntity) -> {
            AttrRespVo attrRespVo = new AttrRespVo();
            BeanUtils.copyProperties(attrEntity, attrRespVo);
            // 给我们的attrRespVo里面进行赋值的操作

            // 设置分类 和 分组的名字
            // 分组 名字 可以从商品属性里面的分组进行查询
            // 我们的分组id需要从relation里面获取出来

            // 我们的销售属性是没有分组的
            if ("base".equalsIgnoreCase(attrType)) {
                AttrAttrgroupRelationEntity attrgroupRelationServiceOne = attrAttrgroupRelationService.getOne(new LambdaQueryWrapper<AttrAttrgroupRelationEntity>().eq(AttrAttrgroupRelationEntity::getAttrId, attrEntity.getAttrId()));
                if (attrgroupRelationServiceOne != null && attrgroupRelationServiceOne.getAttrGroupId() != null) {
                    Long attrGroupId = attrgroupRelationServiceOne.getAttrGroupId();
                    AttrGroupEntity group = attrGroupService.getById(attrGroupId);
                    if (group != null) {
                        attrRespVo.setGroupName(group.getAttrGroupName());

                    }
                }
            }

            // 下面是获取分类名称
            Long catelogId1 = attrEntity.getCatelogId();
            CategoryEntity category = categoryService.getById(catelogId1);
            if (category != null) {
                attrRespVo.setCatelogName(category.getName());
            }


            return attrRespVo;
        }).collect(Collectors.toList());

        PageUtils pageUtils = new PageUtils(page);

        pageUtils.setList(respVos);
        return pageUtils;
    }

    // 额外获取三级分类的路径
    @Override
    public AttrRespVo getAttrInfo(Long attrId) {
        AttrEntity attrEntity = getById(attrId);
        AttrRespVo attrRespVo = new AttrRespVo();
        BeanUtils.copyProperties(attrEntity, attrRespVo);

        // 判断是销售属性不查询分组信息
        if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            // 去关联表里面查询出分组信息
            AttrAttrgroupRelationEntity attrgroupRelation = attrAttrgroupRelationService.getOne(new LambdaQueryWrapper<AttrAttrgroupRelationEntity>().eq(AttrAttrgroupRelationEntity::getAttrId, attrEntity.getAttrId()));

            if (attrgroupRelation != null) {
                AttrGroupEntity group = attrGroupService.getById(attrgroupRelation.getAttrGroupId());

                // 设置名字 也要进行非空的判断
                if (group != null) {
                    String attrGroupName = group.getAttrGroupName();
                    // 还可以设置名字
                    attrRespVo.setGroupName(attrGroupName);
                }

                attrRespVo.setAttrGroupId(attrgroupRelation.getAttrGroupId());
            }
        }


        // 查询出分类信息
        // 使用递归来实现
        // 分类id
        Long catelogId = attrEntity.getCatelogId();
        // 整个完成路径
        // 我们在categoryService里面写过这样的方法
        Long[] catelogPath = categoryService.findCatelogPath(catelogId);
        CategoryEntity category = categoryService.getById(catelogId);

        // 设置名字
        if (category != null) {
            attrRespVo.setCatelogName(category.getName());

        }
        attrRespVo.setCatelogPath(catelogPath);

        return attrRespVo;
    }

    // 修改方法也要进行多张表的修改
    @Transactional
    @Override
    public void updateAttr(AttrVo attrVo) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVo, attrEntity);
        updateById(attrEntity);

        // 如果是基本类型才进行关联表修改
        if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            // 修改分组关联的表
            LambdaQueryWrapper<AttrAttrgroupRelationEntity> LambdaQueryWrapper = new LambdaQueryWrapper<>();
            LambdaQueryWrapper.eq(AttrAttrgroupRelationEntity::getAttrId, attrVo.getAttrId());


            int count = attrAttrgroupRelationService.count(LambdaQueryWrapper);

            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrId(attrVo.getAttrId());
            attrAttrgroupRelationEntity.setAttrGroupId(attrVo.getAttrGroupId());
            // 创建一个对象出来
            if (count > 0) {
                // 修改
                attrAttrgroupRelationService.update(attrAttrgroupRelationEntity, LambdaQueryWrapper);
            } else {
                // 新增
                attrAttrgroupRelationService.save(attrAttrgroupRelationEntity);
            }
        }


    }

    /**
     * 根据分组id查找关联的所有基本属性规格参数
     *
     * @param attrgroupId
     * @return
     */
    @Override
    public List<AttrEntity> getattrRelation(Long attrgroupId) {

        // 根据group_id查询出attr_id
        LambdaQueryWrapper<AttrAttrgroupRelationEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AttrAttrgroupRelationEntity::getAttrGroupId, attrgroupId);
        List<AttrAttrgroupRelationEntity> relationEntityList = attrAttrgroupRelationService.list(lambdaQueryWrapper);

        if (relationEntityList != null) {
            List<Long> attrIds = relationEntityList.stream().map((attr) -> {
                Long attrId = attr.getAttrId();
                return attrId;
            }).collect(Collectors.toList());

            if (attrIds != null && !attrIds.isEmpty()) {
                Collection<AttrEntity> attrEntities = listByIds(attrIds);
                return (List<AttrEntity>) attrEntities;
            }
        }
        return null;
    }


    // 属性分组里面的关联的删除
    @Override
    public void attrRelationDelete(AttrGroupRelationVo[] ovs) {
//        LambdaQueryWrapper<AttrAttrgroupRelationEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//
//        // 只删除关联关系就可以了 属性是不删除的
//        lambdaQueryWrapper.eq(AttrAttrgroupRelationEntity::getAttrId,).eq(AttrAttrgroupRelationEntity::getAttrGroupId,)

        // 实现批量删除
        List<AttrAttrgroupRelationEntity> collect = Arrays.asList(ovs).stream().map((item) -> {
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            BeanUtils.copyProperties(item, attrAttrgroupRelationEntity);
            return attrAttrgroupRelationEntity;
        }).collect(Collectors.toList());


        // 传递我们的AttrAttrgroupRelationEntity的集合
        attrAttrgroupRelationDao.deleteBatchRelation(collect);
    }

    /**
     * 获取当前分组没有关联的所里有规格属性
     * @param attrgroupId
     * @param params
     * @return
     */
    @Override
    public PageUtils getNoRelation(Long attrgroupId, Map<String, Object> params) {

        // 1.当前分组只能关联所属自己所属分类里面的所有属性
        AttrGroupEntity attrGroup = attrGroupService.getById(attrgroupId);

        // 得到分类的id
        Long catelogId = attrGroup.getCatelogId();

        LambdaQueryWrapper<AttrGroupEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 获取所有这个分类下面的所有的
        // 并且不是自己的
        // .ne(AttrGroupEntity::getAttrGroupId,attrgroupId); 我们不能要因为 这样就无法排除自己选了的attrId了
        lambdaQueryWrapper.eq(AttrGroupEntity::getCatelogId,catelogId);

        // 得到所有的分组
        List<AttrGroupEntity> groupEntities = attrGroupService.list(lambdaQueryWrapper);
        // 去除自己的分组
        List<Long> groupIds = groupEntities.stream().map((item) -> {
            return item.getAttrGroupId();
        }).collect(Collectors.toList());

        // 2.当前分组只能关联别的分组没有引用的属性 被引用也不能关联
        // 2.1) 当前分类下的其他分组
        // 2.2) 这些分组关联的属性
        LambdaQueryWrapper<AttrAttrgroupRelationEntity> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper1.in(AttrAttrgroupRelationEntity::getAttrGroupId, groupIds);
        // 获取这个分组下面所有的属性
        List<AttrAttrgroupRelationEntity> list = attrAttrgroupRelationService.list(lambdaQueryWrapper1);

        // 包含了其他分组里面所有的属性id
        List<Long> attrIds = list.stream().map((item) -> {
            return item.getAttrId();
        }).collect(Collectors.toList());

        // 2.3) 从当前分类的所有属性中移除这些属性
        LambdaQueryWrapper<AttrEntity> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();

        // 找出不属于上面被使用过的attrIds就ok了
        // ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() 必须是规格参数  这个表示是既有我们的销售属性和我们的规格参数
        lambdaQueryWrapper2.eq(AttrEntity::getCatelogId,catelogId).eq(AttrEntity::getAttrType, ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()).notIn(attrIds != null && attrIds.size() > 0,AttrEntity::getAttrId,attrIds);
//        List<AttrEntity> attrEntities = list(lambdaQueryWrapper2);

        // 还要排除自己已经选了的


        // 关键字查询
        String key = (String) params.get("key");

        if(!StringUtils.isEmpty(key)) {
            lambdaQueryWrapper2.and((obj) -> {
                obj.eq(AttrEntity::getAttrId,key).or()
                        .like(AttrEntity::getAttrName,key);
            });
        }

        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                lambdaQueryWrapper2
        );

        return new PageUtils(page);
    }

    /**
     * 最终返回能检索的attrIds
     * @param attrIds
     * @return
     */
    @Override
    public List<Long> selectSearchAttrs(List<Long> attrIds) {
        /*
        select * from pms_attr where attr_id in(?) And search_type = 1 被用来检索的
         */
        return baseMapper.selectSearchAttrs(attrIds);
    }


}